<template>
    <n-form
        ref="formRef"
        :rules="rules"
        :model="formData"
        v-bind="formPropsFilter"
    >
        <template v-for="item in formList" :key="item.code">
            <template v-if="showItem(item)">
                <CustomRender
                    v-if="item.render"
                    v-model="formData[item.code]"
                    :data="item"
                    :form-list="formList"
                >
                </CustomRender>
                <n-form-item v-else :label="item.label" :path="item.code">
                    <component
                        :is="item.tag"
                        v-model:value="formData[item.code]"
                        :style="comStyle(item)"
                        v-bind="item.comProps"
                    />
                </n-form-item>
            </template>
        </template>
    </n-form>
</template>

<script setup>
import CustomRender from './CustomRender.vue';
import { isEqual } from './utils';
import { ref, computed } from 'vue';

const props = defineProps({
    formProps: {
        type: Object,
        default: () => ({})
    },
    formItemProps: {
        type: Object,
        default: () => ({})
    },
    formList: {
        type: Array,
        default: () => []
    },
    rules: {
        type: Object,
        default: () => ({})
    }
});
const formRef = ref(null);
const formData = ref({});

const getFormData = () => {
    const result = {};
    props.formList.forEach(item => {
        result[item.code] = showItem(item)
            ? formData.value[item.code]
            : item.nullValue;
    });
    return result;
};
const formPropsFilter = computed(() => {
    const result = {
        labelPlacement: 'left',
        requireMarkPlacement: 'right-hanging',
        labelWidth: 90
    };
    return {
        ...result,
        ...props.formProps
    };
});
const showItem = item => item.visible ?? true;
const comStyle = item => {
    const style = {
        width: '400px'
    };
    return {
        ...style,
        ...props.formItemProps,
        ...item.comStyle
    };
};

// 设置表单字段
const setFormData = data => {
    for (let key in data) {
        const newValue = data[key];
        const currentValue = formData.value[key];
        if (!isEqual(newValue, currentValue)) {
            formData.value[key] = newValue;
        }
    }
};
// 初始化表单字段
const init = () => {
    props.formList.forEach(item => {
        formData.value[item.code] = item.value;
    });
};
init();
defineExpose({
    formRef,
    getFormData,
    setFormData
});
</script>
<style lang="less" scoped>
:deep(.n-form) {
    margin-top: 24px;
}
</style>
